/*test.y*/
%{
#include <stdio.h>
#include <string.h>
#include "crypto/types.h"
#include "crypto/errors.h"
#include "crypto/json.h"
#include "crypto/parse/json/json.l.h"
int yylex(void);
void yyerror(Json **result, char *);
%}

%parse-param {Json **result}

%union{
    char *string;
    double d;
    int64 number;
    Json *json;
    JsonValue *jsonValue;
    JsonItem *jsonItem;
    JsonArray *jsonArray;
    // 这里不能使用typedef定义的，只能采用原始的结构体定义
}
%token <d> _JSON_TYPE_DOUBLE
%token <number> _JSON_TYPE_NUMBER
%token <string> _JSON_TYPE_STRING
%token <string> _JSON_KEY
%token _JSON_TYPE_NULL
%token EOL

%type <json> _json 
%type <jsonItem> _json_item
%type <jsonArray> _json_array
%type <json> _json_end
%type <jsonArray> _json_array_end

%start _JSON_FINAL
%%
    _JSON_FINAL : _json_end EOL { 
        // debug printf("jsonParse: %s\n", JsonStringify($1, NULL));
        // debug printf("end\n");
        *result = $1;
    } 

    _json_end : _json '}' {
    // debug printf("record: %s", JsonStringify($1, NULL));
    $$ = $1;}


    _json_array_end: _json_array ']' {$$ = $1;}


    _json : '{' _json_item  {
        // debug printf("1");
        Json *json = JsonInit();
        JsonPut(json, $2);
        $$ = json;
    }
    | _json ',' _json_item  {
        // debug printf("2");
        JsonPut($1, $3);
        $$ = $1;
    }


    _json_item : _JSON_KEY ':' _JSON_TYPE_STRING {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_STRING;
        jsonValue->value = $3;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("3");
    }
    | _JSON_KEY ':' _JSON_TYPE_NUMBER {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_LONG;
        jsonValue->value = malloc(sizeof(int64));
        *((int64 *)(jsonValue -> value)) = $3;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("4");
    }
    | _JSON_KEY ':' _JSON_TYPE_DOUBLE {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_DOUBLE;
        jsonValue->value = malloc(sizeof(double));
        *((double *)(jsonValue -> value)) = $3;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("5");
    }
    | _JSON_KEY ':' _json_array_end {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_ARRAY;
        jsonValue->value = $3;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("6");
    }
    | _JSON_KEY ':' _json_end {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_JSON;
        jsonValue->value = $3;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("7");
    }
    | _JSON_KEY ':' _JSON_TYPE_NULL {
        JsonValue *jsonValue = (JsonValue *)malloc(sizeof(jsonValue));
        jsonValue->type = JSON_VALUE_TYPE_NUL;
        $$ = JsonItemInit($1, jsonValue);
        // debug printf("8");
    }


    _json_array: '[' _JSON_TYPE_STRING {
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_STRING;
        jsonArray->cap = JSON_ARRAY_INITIAL_CAPACITY;
        jsonArray->len = 1;
        jsonArray->array = malloc(sizeof(char *) * JSON_ARRAY_INITIAL_CAPACITY);
        ((char **)(jsonArray->array))[0] = $2; 
        $$ = jsonArray;
        // debug printf("9");
    }
    | '[' _JSON_TYPE_NUMBER {
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_LONG;
        jsonArray->cap = JSON_ARRAY_INITIAL_CAPACITY;
        jsonArray->len = 1;
        jsonArray->array = malloc(sizeof(char *) * JSON_ARRAY_INITIAL_CAPACITY);
        (((int64*)jsonArray->array)[0]) = $2;
        $$ = jsonArray;
        // debug printf("10");
    }
    | '[' _JSON_TYPE_DOUBLE {
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_DOUBLE;
        jsonArray->cap = JSON_ARRAY_INITIAL_CAPACITY;
        jsonArray->len = 1;
        jsonArray->array = malloc(sizeof(char *) * JSON_ARRAY_INITIAL_CAPACITY);
        ((double *)(jsonArray->array))[0] = $2;
        $$ = jsonArray;
        // debug printf("11");
    }
    | '[' _json_array_end {
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_ARRAY;
        jsonArray->cap = JSON_ARRAY_INITIAL_CAPACITY;
        jsonArray->len = 1;
        jsonArray->array = malloc(sizeof(char *) * JSON_ARRAY_INITIAL_CAPACITY);
        ((JsonArray **)(jsonArray->array))[0] = $2;
        $$ = jsonArray;
        // debug printf("12");
    }
    | '[' _json_end {  
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_JSON;
        jsonArray->cap = JSON_ARRAY_INITIAL_CAPACITY;
        jsonArray->len = 1;
        jsonArray->array = malloc(sizeof(char *) * JSON_ARRAY_INITIAL_CAPACITY);
        ((Json **)(jsonArray->array))[0] = $2;
        $$ = jsonArray;
        // debug printf("13");
    }
    | '[' _JSON_TYPE_NULL {
        JsonArray *jsonArray = JsonArrayInit();
        jsonArray->type = JSON_VALUE_TYPE_NUL;
        jsonArray->len = 1;
        $$ = jsonArray;
        // debug printf("14");
    }
    | _json_array ',' _JSON_TYPE_STRING {
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_STRING)
        {
            // debug printf("error\n");
        }
        if (jsonArray->len == jsonArray->cap)
        {
            int newSize = jsonArray->cap * 2;
            void * value = malloc(sizeof(char *) * newSize);
            memcpy(value ,jsonArray->array, jsonArray->cap);
            free(jsonArray->array);
            jsonArray->array = value;
            jsonArray->cap *= 2;
        }
        ((char **)(jsonArray->array))[jsonArray->len] = $3;
        jsonArray->len ++;
        // debug printf("15");
    }
    | _json_array ',' _JSON_TYPE_NUMBER {
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_LONG)
        {
            // debug printf("error\n");
        }
        if (jsonArray->len == jsonArray->cap)
        {
            int newSize = jsonArray->cap * 2;
            void * value = malloc(sizeof(char *) * newSize);
            memcpy(value ,jsonArray->array, jsonArray->cap);
            free(jsonArray->array);
            jsonArray->array = value;
            jsonArray->cap *= 2;
        }
        ((int64 *)(jsonArray->array))[jsonArray->len] = $3;
        jsonArray->len ++;
        // debug printf("16");
    }
    | _json_array ',' _JSON_TYPE_DOUBLE {
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_DOUBLE)
        {
            // debug printf("error\n");
        }
        if (jsonArray->len == jsonArray->cap)
        {
            int newSize = jsonArray->cap * 2;
            void * value = malloc(sizeof(char *) * newSize);
            memcpy(value ,jsonArray->array, jsonArray->cap);
            free(jsonArray->array);
            jsonArray->array = value;
            jsonArray->cap *= 2;
        }
        ((double *)(jsonArray->array))[jsonArray->len] = $3;
        jsonArray->len ++;
        // debug printf("17");
    }
    | _json_array ',' _json_array_end {
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_ARRAY)
        {
        
        }
        if (jsonArray->len == jsonArray->cap)
        {
            int newSize = jsonArray->cap * 2;
            void * value = malloc(sizeof(char *) * newSize);
            memcpy(value ,jsonArray->array, jsonArray->cap);
            free(jsonArray->array);
            jsonArray->array = value;
            jsonArray->cap *= 2;
        }
        ((JsonArray **)(jsonArray->array))[jsonArray->len] = $3;
        jsonArray->len ++;
        // debug printf("18");
    }
    | _json_array ',' _json_end {
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_JSON)
        {
            // debug printf("error\n");
        }
        if (jsonArray->len == jsonArray->cap)
        {
            int newSize = jsonArray->cap * 2;
            void * value = malloc(sizeof(char *) * newSize);
            memcpy(value ,jsonArray->array, jsonArray->cap);
            free(jsonArray->array);
            jsonArray->array = value;
            jsonArray->cap *= 2;
        }
        ((Json **)(jsonArray->array))[jsonArray->len] = $3;
        jsonArray->len ++;
        // debug printf("19");
    }
    | _json_array ',' _JSON_TYPE_NULL{
        JsonArray *jsonArray = $1;
        if (jsonArray->type != JSON_VALUE_TYPE_NUL)
        {
            
        }
        jsonArray->len ++;
        // debug printf("20");
    }

%%
void yyerror(Json **result, char *msg){
    *result = NULL;
    fprintf(stderr,"%d: %s at '%s'\n", yylineno, msg, yytext);
}


